﻿using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using NewLife.Messaging;
using Newtonsoft.Json.Linq;
using RedisHelp;
using StackExchange.Redis;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

namespace GXRTBTC.PublicClassLibrary.Redis
{
    /// <summary>
    /// 为了在使用批处理程序时，也能统一使用CustomKey参数
    /// 此举是为了在读写redis时，统一服务相关的key有一个统一的前缀，和其它的区分开来
    /// </summary>
    public static class MyRedisCommon
    {
        /// <summary>
        /// 设置自定义键
        /// </summary>
        public static string CustomKey { get; set; } = "svr_";

        /// <summary>
        /// 添加自定义键
        /// </summary>
        /// <param name="oldKey"></param>
        /// <returns></returns>
        public static string AddSysCustomKey(string oldKey)
        {
            var prefixKey = CustomKey ?? RedisConnectionHelp.SysCustomKey;
            return prefixKey + oldKey;
        }

        private static RedisKey[] ConvertRedisKeys(List<string> redisKeys)
        {
            return redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();
        }

        public static void MExecute(this IBatch batch)
        {
            batch.Execute();
        }

        public static Task<long> MHashDecrementAsync(this IBatch batch, RedisKey key, RedisValue hashField, long value = 1, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashDecrementAsync(AddSysCustomKey(key), hashField, value, flags);
        }

        public static Task<double> MHashDecrementAsync(this IBatch batch, RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashDecrementAsync(AddSysCustomKey(key), hashField, value, flags);
        }

        public static Task<bool> MHashDeleteAsync(this IBatch batch, RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashDeleteAsync(AddSysCustomKey(key), hashField, flags);    
        }

        public static Task<long> MHashDeleteAsync(this IBatch batch, RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashDeleteAsync(AddSysCustomKey(key), hashFields, flags);
        }

        public static Task<bool> MHashExistsAsync(this IBatch batch, RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashExistsAsync(AddSysCustomKey(key), hashField, flags);
        }

        public static Task<ExpireResult[]> MHashFieldExpireAsync(this IBatch batch, RedisKey key, RedisValue[] hashFields, TimeSpan expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashFieldExpireAsync(AddSysCustomKey(key), hashFields, expiry, when, flags);
        }

        public static Task<ExpireResult[]> MHashFieldExpireAsync(this IBatch batch, RedisKey key, RedisValue[] hashFields, DateTime expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashFieldExpireAsync(AddSysCustomKey(key), hashFields, expiry, when, flags);
        }

        public static Task<long[]> MHashFieldGetExpireDateTimeAsync(this IBatch batch, RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashFieldGetExpireDateTimeAsync(AddSysCustomKey(key), hashFields, flags);
        }

        public static Task<long[]> MHashFieldGetTimeToLiveAsync(this IBatch batch, RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashFieldGetTimeToLiveAsync(AddSysCustomKey(key), hashFields, flags);
        }

        public static Task<PersistResult[]> MHashFieldPersistAsync(this IBatch batch, RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashFieldPersistAsync(AddSysCustomKey(key), hashFields, flags);
        }

        public static Task<HashEntry[]> MHashGetAllAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashGetAllAsync(AddSysCustomKey(key), flags);
        }

        public static Task<RedisValue> MHashGetAsync(this IBatch batch, RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashGetAsync(AddSysCustomKey(key), hashField, flags);
        }

        public static Task<RedisValue[]> MHashGetAsync(this IBatch batch, RedisKey key, RedisValue[] hashFields, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashGetAsync(AddSysCustomKey(key), hashFields, flags);
        }

        public static Task<Lease<byte>> MHashGetLeaseAsync(this IBatch batch, RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashGetLeaseAsync(AddSysCustomKey(key), hashField, flags);
        }

        public static Task<long> MHashIncrementAsync(this IBatch batch, RedisKey key, RedisValue hashField, long value = 1, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashIncrementAsync(AddSysCustomKey(key), hashField, value, flags);
        }

        public static Task<double> MHashIncrementAsync(this IBatch batch, RedisKey key, RedisValue hashField, double value, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashIncrementAsync(AddSysCustomKey(key), hashField, value, flags);
        }

        public static Task<RedisValue[]> MHashKeysAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashKeysAsync(AddSysCustomKey(key), flags);
        }

        public static Task<long> MHashLengthAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashLengthAsync(AddSysCustomKey(key), flags);
        }

        public static Task<RedisValue> MHashRandomFieldAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashRandomFieldAsync(AddSysCustomKey(key), flags);
        }

        public static Task<RedisValue[]> MHashRandomFieldsAsync(this IBatch batch, RedisKey key, long count, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashRandomFieldsAsync(AddSysCustomKey(key), count, flags);
        }

        public static Task<HashEntry[]> MHashRandomFieldsWithValuesAsync(this IBatch batch, RedisKey key, long count, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashRandomFieldsWithValuesAsync(AddSysCustomKey(key), count, flags);
        }

        public static IAsyncEnumerable<HashEntry> MHashScanAsync(this IBatch batch, RedisKey key, RedisValue pattern = default, int pageSize = 250, long cursor = 0, int pageOffset = 0, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashScanAsync(AddSysCustomKey(key), pattern, pageSize, cursor, pageOffset, flags);
        }

        public static IAsyncEnumerable<RedisValue> MHashScanNoValuesAsync(this IBatch batch, RedisKey key, RedisValue pattern = default, int pageSize = 250, long cursor = 0, int pageOffset = 0, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashScanNoValuesAsync(AddSysCustomKey(key), pattern, pageSize, cursor, pageOffset, flags);
        }

        public static Task MHashSetAsync(this IBatch batch, RedisKey key, HashEntry[] hashFields, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashSetAsync(AddSysCustomKey(key), hashFields, flags);
        }

        public static Task<bool> MHashSetAsync(this IBatch batch, RedisKey key, RedisValue hashField, RedisValue value, When when = When.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashSetAsync(AddSysCustomKey(key), hashField, value, when, flags);
        }

        public static Task<long> MHashStringLengthAsync(this IBatch batch, RedisKey key, RedisValue hashField, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashStringLengthAsync(AddSysCustomKey(key), hashField, flags);
        }

        public static Task<RedisValue[]> MHashValuesAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.HashValuesAsync(AddSysCustomKey(key), flags);
        }

        public static bool MIsConnected(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.IsConnected(AddSysCustomKey(key), flags);
        }

        public static Task<bool> MKeyCopyAsync(this IBatch batch, RedisKey sourceKey, RedisKey destinationKey, int destinationDatabase = -1, bool replace = false, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyCopyAsync(AddSysCustomKey(sourceKey), AddSysCustomKey(destinationKey), destinationDatabase, replace, flags);
        }

        public static Task<bool> MKeyDeleteAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyDeleteAsync(AddSysCustomKey(key), flags);
        }

        public static Task<long> MKeyDeleteAsync(this IBatch batch, RedisKey[] keys, CommandFlags flags = CommandFlags.None)
        {
            List<string> newKeys = keys.Select(redisKey => AddSysCustomKey(redisKey.ToString())).ToList();
            return batch.KeyDeleteAsync(ConvertRedisKeys(newKeys), flags);
        }

        public static Task<byte[]> MKeyDumpAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyDumpAsync(AddSysCustomKey(key), flags);
        }

        public static Task<string> MKeyEncodingAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyEncodingAsync(AddSysCustomKey(key), flags);
        }

        public static Task<bool> MKeyExistsAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyExistsAsync(AddSysCustomKey(key), flags);
        }

        public static Task<long> MKeyExistsAsync(this IBatch batch, RedisKey[] keys, CommandFlags flags = CommandFlags.None)
        {
            List<string> newKeys = keys.Select(redisKey => AddSysCustomKey(redisKey.ToString())).ToList();
            return batch.KeyExistsAsync(ConvertRedisKeys(newKeys), flags);
        }

        public static Task<bool> MKeyExpireAsync(this IBatch batch, RedisKey key, TimeSpan? expiry, CommandFlags flags)
        {
            return batch.KeyExpireAsync(AddSysCustomKey(key), expiry, flags);
        }

        public static Task<bool> MKeyExpireAsync(this IBatch batch, RedisKey key, TimeSpan? expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyExpireAsync(AddSysCustomKey(key), expiry, when, flags);
        }

        public static Task<bool> MKeyExpireAsync(this IBatch batch, RedisKey key, DateTime? expiry, CommandFlags flags)
        {
            return batch.KeyExpireAsync(AddSysCustomKey(key), expiry, flags);
        }

        public static Task<bool> MKeyExpireAsync(this IBatch batch, RedisKey key, DateTime? expiry, ExpireWhen when = ExpireWhen.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyExpireAsync(AddSysCustomKey(key), expiry, when, flags);
        }

        public static Task<DateTime?> MKeyExpireTimeAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyExpireTimeAsync(AddSysCustomKey(key), flags);
        }

        public static Task<long?> MKeyFrequencyAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyFrequencyAsync(AddSysCustomKey(key), flags);
        }

        public static Task<TimeSpan?> MKeyIdleTimeAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyIdleTimeAsync(AddSysCustomKey(key), flags);
        }

        public static Task MKeyMigrateAsync(this IBatch batch, RedisKey key, EndPoint toServer, int toDatabase = 0, int timeoutMilliseconds = 0, MigrateOptions migrateOptions = MigrateOptions.None, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyMigrateAsync(AddSysCustomKey(key), toServer, toDatabase, timeoutMilliseconds, migrateOptions, flags);
        }

        public static Task<bool> MKeyMoveAsync(this IBatch batch, RedisKey key, int database, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyMoveAsync(AddSysCustomKey(key), database, flags);
        }

        public static Task<bool> MKeyPersistAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyPersistAsync(AddSysCustomKey(key), flags);
        }

        public static Task<long?> MKeyRefCountAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyRefCountAsync(AddSysCustomKey(key), flags);
        }

        public static Task<bool> MKeyRenameAsync(this IBatch batch, RedisKey key, RedisKey newKey, When when = When.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyRenameAsync(AddSysCustomKey(key), AddSysCustomKey(newKey), when, flags);
        }

        public static Task MKeyRestoreAsync(this IBatch batch, RedisKey key, byte[] value, TimeSpan? expiry = null, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyRestoreAsync(AddSysCustomKey(key), value, expiry, flags);
        }

        public static Task<TimeSpan?> MKeyTimeToLiveAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyTimeToLiveAsync(AddSysCustomKey(key), flags);
        }

        public static Task<bool> MKeyTouchAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyTouchAsync(AddSysCustomKey(key), flags);
        }

        public static Task<long> MKeyTouchAsync(this IBatch batch, RedisKey[] keys, CommandFlags flags = CommandFlags.None)
        {
            List<string> newKeys = keys.Select(redisKey => AddSysCustomKey(redisKey.ToString())).ToList();
            return batch.KeyTouchAsync(ConvertRedisKeys(newKeys), flags);
        }

        public static Task<RedisType> MKeyTypeAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.KeyTypeAsync(AddSysCustomKey(key), flags);
        }


        public static Task<long> MPublishAsync(this IBatch batch, RedisChannel channel, RedisValue message, CommandFlags flags = CommandFlags.None)
        {
            return batch.PublishAsync(AddSysCustomKey(channel), message, flags);
        }

        public static Task<long> MStringAppendAsync(this IBatch batch, RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringAppendAsync(AddSysCustomKey(key), value, flags);
        }

        public static Task<long> MStringBitCountAsync(this IBatch batch, RedisKey key, long start, long end, CommandFlags flags)
        {
            return batch.StringBitCountAsync(AddSysCustomKey(key), start, end, flags);
        }

        public static Task<long> MStringBitCountAsync(this IBatch batch, RedisKey key, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringBitCountAsync(AddSysCustomKey(key), start, end, indexType, flags);
        }

        public static Task<long> MStringBitOperationAsync(this IBatch batch, Bitwise operation, RedisKey destination, RedisKey first, RedisKey second = default, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringBitOperationAsync(operation, AddSysCustomKey(destination), AddSysCustomKey(first), AddSysCustomKey(second), flags);
        }

        public static Task<long> MStringBitOperationAsync(this IBatch batch, Bitwise operation, RedisKey destination, RedisKey[] keys, CommandFlags flags = CommandFlags.None)
        {
            List<string> newKeys = keys.Select(redisKey => AddSysCustomKey(redisKey.ToString())).ToList();
            return batch.StringBitOperationAsync(operation, AddSysCustomKey(destination), ConvertRedisKeys(newKeys), flags);
        }

        public static Task<long> MStringBitPositionAsync(this IBatch batch, RedisKey key, bool bit, long start, long end, CommandFlags flags)
        {
            return batch.StringBitPositionAsync(AddSysCustomKey(key), bit, start, end, flags);
        }

        public static Task<long> MStringBitPositionAsync(this IBatch batch, RedisKey key, bool bit, long start = 0, long end = -1, StringIndexType indexType = StringIndexType.Byte, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringBitPositionAsync(AddSysCustomKey(key), bit, start, end, indexType, flags);
        }

        public static Task<long> MStringDecrementAsync(this IBatch batch, RedisKey key, long value = 1, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringDecrementAsync(AddSysCustomKey(key), value, flags);
        }

        public static Task<double> MStringDecrementAsync(this IBatch batch, RedisKey key, double value, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringDecrementAsync(AddSysCustomKey(key), value, flags);
        }

        public static Task<RedisValue> MStringGetAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetAsync(AddSysCustomKey(key), flags);
        }

        public static Task<RedisValue[]> MStringGetAsync(this IBatch batch, RedisKey[] keys, CommandFlags flags = CommandFlags.None)
        {
            List<string> newKeys = keys.Select(redisKey => AddSysCustomKey(redisKey.ToString())).ToList();
            return batch.StringGetAsync(ConvertRedisKeys(newKeys), flags);
        }

        public static Task<bool> MStringGetBitAsync(this IBatch batch, RedisKey key, long offset, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetBitAsync(AddSysCustomKey(key), offset, flags);
        }

        public static Task<RedisValue> MStringGetDeleteAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetDeleteAsync(AddSysCustomKey(key), flags);
        }

        public static Task<Lease<byte>> MStringGetLeaseAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetLeaseAsync(AddSysCustomKey(key), flags);
        }

        public static Task<RedisValue> MStringGetRangeAsync(this IBatch batch, RedisKey key, long start, long end, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetRangeAsync(AddSysCustomKey(key), start, end, flags);
        }

        public static Task<RedisValue> MStringGetSetAsync(this IBatch batch, RedisKey key, RedisValue value, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetSetAsync(AddSysCustomKey(key), value, flags);
        }

        public static Task<RedisValue> MStringGetSetExpiryAsync(this IBatch batch, RedisKey key, TimeSpan? expiry, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetSetExpiryAsync(AddSysCustomKey(key), expiry, flags);
        }

        public static Task<RedisValue> MStringGetSetExpiryAsync(this IBatch batch, RedisKey key, DateTime expiry, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetSetExpiryAsync(AddSysCustomKey(key), expiry, flags);
        }

        public static Task<RedisValueWithExpiry> MStringGetWithExpiryAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringGetWithExpiryAsync(AddSysCustomKey(key), flags);
        }

        public static Task<long> MStringIncrementAsync(this IBatch batch, RedisKey key, long value = 1, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringIncrementAsync(AddSysCustomKey(key), value, flags);
        }

        public static Task<double> MStringIncrementAsync(this IBatch batch, RedisKey key, double value, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringIncrementAsync(AddSysCustomKey(key), value, flags);
        }

        public static Task<long> mStringLengthAsync(this IBatch batch, RedisKey key, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringLengthAsync(AddSysCustomKey(key), flags);
        }

        public static Task<string> MStringLongestCommonSubsequenceAsync(this IBatch batch, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringLongestCommonSubsequenceAsync(AddSysCustomKey(first), AddSysCustomKey(second), flags);
        }

        public static Task<long> MStringLongestCommonSubsequenceLengthAsync(this IBatch batch, RedisKey first, RedisKey second, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringLongestCommonSubsequenceLengthAsync(AddSysCustomKey(first), AddSysCustomKey(second), flags);
        }

        public static Task<LCSMatchResult> MStringLongestCommonSubsequenceWithMatchesAsync(this IBatch batch, RedisKey first, RedisKey second, long minLength = 0, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringLongestCommonSubsequenceWithMatchesAsync(AddSysCustomKey(first), AddSysCustomKey(second), minLength, flags);
        }

        public static Task<RedisValue> MStringSetAndGetAsync(this IBatch batch, RedisKey key, RedisValue value, TimeSpan? expiry, When when, CommandFlags flags)
        {
            return batch.StringSetAndGetAsync(AddSysCustomKey(key), value, expiry, when, flags);
        }

        public static Task<RedisValue> MStringSetAndGetAsync(this IBatch batch, RedisKey key, RedisValue value, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringSetAndGetAsync(AddSysCustomKey(key), value, expiry, keepTtl, when, flags);
        }

        public static Task<bool> MStringSetAsync(this IBatch batch, RedisKey key, RedisValue value, TimeSpan? expiry, When when)
        {
            return batch.StringSetAsync(AddSysCustomKey(key), value, expiry, when);
        }

        public static Task<bool> MStringSetAsync(this IBatch batch, RedisKey key, RedisValue value, TimeSpan? expiry, When when, CommandFlags flags)
        {
            return batch.StringSetAsync(AddSysCustomKey(key), value, expiry, when, flags);
        }

        public static Task<bool> MStringSetAsync(this IBatch batch, RedisKey key, RedisValue value, TimeSpan? expiry = null, bool keepTtl = false, When when = When.Always, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringSetAsync(AddSysCustomKey(key), value, expiry, keepTtl, when, flags);
        }

        public static Task<bool> MStringSetAsync(this IBatch batch, KeyValuePair<RedisKey, RedisValue>[] values, When when = When.Always, CommandFlags flags = CommandFlags.None)
        {
            List<KeyValuePair<RedisKey, RedisValue>> newValues = values.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToList();
            return batch.StringSetAsync(newValues.ToArray(), when, flags);
        }

        public static Task<bool> MStringSetBitAsync(this IBatch batch, RedisKey key, long offset, bool bit, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringSetBitAsync(AddSysCustomKey(key), offset, bit, flags);
        }

        public static Task<RedisValue> MStringSetRangeAsync(this IBatch batch, RedisKey key, long offset, RedisValue value, CommandFlags flags = CommandFlags.None)
        {
            return batch.StringSetRangeAsync(AddSysCustomKey(key), offset, value, flags);
        }
    }
}
